package com.ffcs.crmd.tsp.client.core;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;

import com.ffcs.crmd.tsp.api.client.IClient;
import com.ffcs.crmd.tsp.api.dto.client.TspCluster;
import com.ffcs.crmd.tsp.api.dto.client.TspClusterInstance;
import com.ffcs.crmd.tsp.api.dto.client.TspJob;
import com.ffcs.crmd.tsp.api.dto.client.TspJobDetail;
import com.ffcs.crmd.tsp.api.dto.client.TspJobDetailDeath;
import com.ffcs.crmd.tsp.api.dto.client.TspJobDetailParam;
import com.ffcs.crmd.tsp.api.dto.client.TspJobDetailRetry;
import com.ffcs.crmd.tsp.api.dto.client.TspJobDetailRunning;
import com.ffcs.crmd.tsp.api.dto.client.TspJobDetailThreadInfo;
import com.ffcs.crmd.tsp.api.dto.client.TspJobDetailTrack;
import com.ffcs.crmd.tsp.api.dto.client.TspJobDetailWaiting;
import com.ffcs.crmd.tsp.api.dto.client.TspJobGroup;
import com.ffcs.crmd.tsp.api.dto.client.TspJobIdentityInfo;
import com.ffcs.crmd.tsp.api.dto.client.TspResult;
import com.ffcs.crmd.tsp.api.dto.client.TspSlice;
import com.ffcs.crmd.tsp.api.dto.client.TspSliceGroup;
import com.ffcs.crmd.tsp.api.dto.client.TspTaskConnectInfo;
import com.ffcs.crmd.tsp.api.dto.client.TspTaskIdentity;
import com.ffcs.crmd.tsp.api.dto.page.RetVo;
import com.ffcs.crmd.tsp.api.netty.INettyConfigClient;
import com.ffcs.crmd.tsp.client.log.ClientLogger;
import com.ffcs.crmd.tsp.client.netty.NettyConfig;
import com.ffcs.crmd.tsp.common.client.enu.TspResultType;
import com.ffcs.crmd.tsp.common.constant.LoggerName;
import com.ffcs.crmd.tsp.common.enu.ServiceState;
import com.ffcs.crmd.tsp.common.exception.TspException;
import com.ffcs.crmd.tsp.common.exception.TspRemotingException;
import com.ffcs.crmd.tsp.common.netty.RequestResult;
import com.ffcs.crmd.tsp.common.netty.enu.NettyRequestResult;
import com.ffcs.crmd.tsp.core.util.XmlUtil;

/**
 * 
 * 功能说明:Tsp客户端
 *
 * @author ZHONGFUHUA
 * 
 * @since 1.0.0-SNAPSHOT
 *
 */
public class TspClient implements IClient {
    
    /**
     * 日志
     */
    private final static Logger LOG                      = ClientLogger.getLogger(LoggerName.ClientLoggerName);
    
    /**
     * 服务端回调线程池大小
     */
    private int                 callbackExecutorThreads  = 5;
    
    /**
     * futureChannel连接超时时间
     */
    private long                connectTimeoutMillis     = 10 * 1000;
    
    /**
     * 发送心跳间隔时间
     */
    private long                heartbeatBrokerInterval  = 30 * 1000;
    
    /**
     * netty服务器端口
     */
    private int                 listenPort               = 1314;
    
    /**
     * 信号量，Oneway情况会使用，防止本地Netty缓存请求过多
     */
    private int                 permitsAsync             = 60000;
    
    /**
     * 信号量，异步调用情况会使用，防止本地Netty缓存请求过多
     */
    private int                 permitsOneway            = 60000;
    
    /**
     * 服务端处理请求线程池大小
     */
    private int                 processorExecutorThreads = 20;
    
    /**
     * 请求超时时间
     */
    private long                sendTimeout              = 10 * 1000;
    
    /**
     * 服务器地址
     */
    private String              serverAddr;
    
    /**
     * 任务执行端启动状态
     */
    private ServiceState        serviceState             = ServiceState.CREATE_JUST;
    
    /**
     * 通信客户端
     */
    private TspClientIntance    tspNettyIntance;
    
    /**
     * boss循环器线程数
     */
    private int                 workGroupThreads         = 20;
    
    public TspClient() {
        
    }
    
    public TspClient(String serverAddr) {
        this.serverAddr = serverAddr;
    }
    
    @Override
    public TspResult<?> createJob(TspJob request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.createJob(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    @Override
    public TspResult<?> createJobDetail(TspJobDetail request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.createJobDetail(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> createJobDetailParam(TspJobDetailParam request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.createJobDetailParam(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    @Override
    public TspResult<?> createJobGroup(TspJobGroup request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.createJobGroup(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    @Override
    public TspResult<?> createJobIdentityInfo(TspJobIdentityInfo request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.createJobIdentityInfo(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> createSlice(TspSlice request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.createSlice(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> createSliceGroup(TspSliceGroup request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.createSliceGroup(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> createTaskIdentity(TspTaskIdentity request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.createTaskIdentity(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> deleteJob(TspJob request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.deleteJob(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    @Override
    public TspResult<?> deleteJobDetail(TspJobDetail request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.deleteJobDetail(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> deleteJobDetailDeath(TspJobDetailDeath request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.deleteJobDetailDeath(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> deleteJobDetailParam(TspJobDetailParam request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.deleteJobDetailParam(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> deleteJobDetailRunning(TspJobDetailRunning request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.deleteJobDetailRunning(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> deleteJobGroup(TspJobGroup request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.deleteJobGroup(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> deleteJobIdentityInfo(TspJobIdentityInfo request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.deleteJobIdentityInfo(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    @Override
    public TspResult<?> deleteSlice(TspSlice request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.deleteSlice(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    @Override
    public TspResult<?> deleteSliceGroup(TspSliceGroup request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.deleteSliceGroup(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> deleteTaskIdentity(TspTaskIdentity request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.deleteTaskIdentity(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    /**
     * 功能说明: 获取服务端回调线程池大小
     *
     * @return callbackExecutorThreads 服务端回调线程池大小
     */
    @Override
    public int getCallbackExecutorThreads() {
        return callbackExecutorThreads;
    }
    
    
    /**
     * 功能说明: 获取futureChannel连接超时时间
     *
     * @return connectTimeoutMillis futureChannel连接超时时间
     */
    @Override
    public long getConnectTimeoutMillis() {
        return connectTimeoutMillis;
    }
    
    
    /**
     * 功能说明: 获取发送心跳间隔时间
     *
     * @return heartbeatBrokerInterval 发送心跳间隔时间
     */
    @Override
    public long getHeartbeatBrokerInterval() {
        return heartbeatBrokerInterval;
    }
    
    
    /**
     * 功能说明: 获取netty服务器端口
     *
     * @return listenPort netty服务器端口
     */
    @Override
    public int getListenPort() {
        return listenPort;
    }
    
    
    /**
     * 功能说明: 获取信号量，Oneway情况会使用，防止本地Netty缓存请求过多
     *
     * @return permitsAsync 信号量，Oneway情况会使用，防止本地Netty缓存请求过多
     */
    @Override
    public int getPermitsAsync() {
        return permitsAsync;
    }
    
    
    /**
     * 功能说明: 获取信号量，异步调用情况会使用，防止本地Netty缓存请求过多
     *
     * @return permitsOneway 信号量，异步调用情况会使用，防止本地Netty缓存请求过多
     */
    @Override
    public int getPermitsOneway() {
        return permitsOneway;
    }
    
    
    /**
     * 功能说明: 获取服务端处理请求线程池大小
     *
     * @return processorExecutorThreads 服务端处理请求线程池大小
     */
    @Override
    public int getProcessorExecutorThreads() {
        return processorExecutorThreads;
    }
    
    
    /**
     * 功能说明: 获取请求超时时间
     *
     * @return sendTimeout 请求超时时间
     */
    @Override
    public long getSendTimeout() {
        return sendTimeout;
    }
    
    
    /**
     * 功能说明: 获取服务器地址
     *
     * @return serverAddr 服务器地址
     */
    @Override
    public String getServerAddr() {
        return serverAddr;
    }
    
    
    /**
     * 功能说明: 获取任务执行端启动状态
     *
     * @return serviceState 任务执行端启动状态
     */
    @Override
    public ServiceState getServiceState() {
        return serviceState;
    }
    
    
    /**
     * 功能说明: 获取boss循环器线程数
     *
     * @return workGroupThreads boss循环器线程数
     */
    @Override
    public int getWorkGroupThreads() {
        return workGroupThreads;
    }
    
    
    /**
     * 功能说明:
     * 
     * @param tspJobDetailRunningList
     * @return
     */
    public TspResult<?> interruptJob(List<TspJobDetailRunning> tspJobDetailRunningList) {
        // TODO Auto-generated method stub
        return null;
    }
    
    
    @Override
    public TspResult<?> interruptJob(TspJobDetailRunning request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.interruptJobDetailRunning(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> pauseJob(TspJob request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.pauseJob(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> pauseJobDetail(TspJobDetail request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.pauseJobDetail(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> pauseJobGroup(TspJobGroup request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.pauseJobGroup(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspCluster> queryCluster(TspCluster request) {
        TspResult<TspCluster> tspResult = new TspResult<TspCluster>();
        RequestResult requestResult = tspNettyIntance.queryCluster(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspCluster> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspClusterInstance> queryClusterInstance(TspClusterInstance request) {
        TspResult<TspClusterInstance> tspResult = new TspResult<TspClusterInstance>();
        RequestResult requestResult = tspNettyIntance.queryClusterInstance(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspClusterInstance> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspJob> queryJob(TspJob request) {
        TspResult<TspJob> tspResult = new TspResult<TspJob>();
        RequestResult requestResult = tspNettyIntance.queryJob(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspJob> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspJobDetail> queryJobDetail(TspJobDetail request) {
        TspResult<TspJobDetail> tspResult = new TspResult<TspJobDetail>();
        RequestResult requestResult = tspNettyIntance.queryJobDetail(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspJobDetail> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspJobDetailDeath> queryJobDetailDeath(TspJobDetailDeath request) {
        TspResult<TspJobDetailDeath> tspResult = new TspResult<TspJobDetailDeath>();
        RequestResult requestResult = tspNettyIntance.queryJobDetailDeath(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspJobDetailDeath> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspJobDetailParam> queryJobDetailParam(TspJobDetailParam request) {
        TspResult<TspJobDetailParam> tspResult = new TspResult<TspJobDetailParam>();
        RequestResult requestResult = tspNettyIntance.queryJobDetailParam(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspJobDetailParam> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspJobDetailRetry> queryJobDetailRetry(TspJobDetailRetry request) {
        TspResult<TspJobDetailRetry> tspResult = new TspResult<TspJobDetailRetry>();
        RequestResult requestResult = tspNettyIntance.queryJobDetailRetry(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspJobDetailRetry> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspJobDetailRunning> queryJobDetailRunning(TspJobDetailRunning request) {
        TspResult<TspJobDetailRunning> tspResult = new TspResult<TspJobDetailRunning>();
        RequestResult requestResult = tspNettyIntance.queryJobDetailRunning(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspJobDetailRunning> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspJobDetailThreadInfo> queryJobDetailThreadInfo(TspJobDetailRunning request) {
        TspResult<TspJobDetailThreadInfo> tspResult = new TspResult<TspJobDetailThreadInfo>();
        RequestResult requestResult = tspNettyIntance.queryJobDetailThreadInfo(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspJobDetailThreadInfo> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspJobDetailTrack> queryJobDetailTrack(TspJobDetailTrack request) {
        TspResult<TspJobDetailTrack> tspResult = new TspResult<TspJobDetailTrack>();
        RequestResult requestResult = tspNettyIntance.queryJobDetailTrack(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspJobDetailTrack> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspJobDetailWaiting> queryJobDetailWaiting(TspJobDetailWaiting request) {
        TspResult<TspJobDetailWaiting> tspResult = new TspResult<TspJobDetailWaiting>();
        RequestResult requestResult = tspNettyIntance.queryJobDetailWaiting(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspJobDetailWaiting> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspJobGroup> queryJobGroup(TspJobGroup request) {
        TspResult<TspJobGroup> tspResult = new TspResult<TspJobGroup>();
        RequestResult requestResult = tspNettyIntance.queryJobGroup(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspJobGroup> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspJobIdentityInfo> queryJobIdentityInfo(TspJobIdentityInfo request) {
        TspResult<TspJobIdentityInfo> tspResult = new TspResult<TspJobIdentityInfo>();
        RequestResult requestResult = tspNettyIntance.queryJobIdentityInfo(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspJobIdentityInfo> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspSlice> querySlice(TspSlice request) {
        TspResult<TspSlice> tspResult = new TspResult<TspSlice>();
        RequestResult requestResult = tspNettyIntance.querySlice(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspSlice> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspSliceGroup> querySliceGroup(TspSliceGroup request) {
        TspResult<TspSliceGroup> tspResult = new TspResult<TspSliceGroup>();
        RequestResult requestResult = tspNettyIntance.querySliceGroup(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspSliceGroup> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspTaskConnectInfo> queryTaskConnectInfo(TspTaskConnectInfo request) {
        TspResult<TspTaskConnectInfo> tspResult = new TspResult<TspTaskConnectInfo>();
        RequestResult requestResult = tspNettyIntance.queryTaskConnectInfo(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspTaskConnectInfo> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public TspResult<TspTaskIdentity> queryTaskIdentity(TspTaskIdentity request) {
        TspResult<TspTaskIdentity> tspResult = new TspResult<TspTaskIdentity>();
        RequestResult requestResult = tspNettyIntance.queryTaskIdentity(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        } else {
            RetVo<TspTaskIdentity> retVo = XmlUtil.fromXml(requestResult.getBody(), RetVo.class);
            tspResult.setRetVo(retVo);
        }
        return tspResult;
    }
    
    @Override
    public TspResult<?> resetJobDetailDeath(TspJobDetailDeath request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.resetJobDetailDeath(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    /**
     * 功能说明:
     * 
     * @param tspJobDetailRunningList
     * @return
     */
    public TspResult<?> resetJobDetailOffline(List<TspJobDetailRunning> tspJobDetailRunningList) {
        // TODO Auto-generated method stub
        return null;
    }
    
    @Override
    public TspResult<?> resetJobDetailRunning(TspJobDetailRunning request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.resetJobDetailRunning(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    /**
     * 功能说明:
     * 
     * @param tspJobDetailRunningList
     * @return
     */
    public TspResult<?> resetJobDetailTimeout(List<TspJobDetailRunning> tspJobDetailRunningList) {
        // TODO Auto-generated method stub
        return null;
    }
    
    @Override
    public TspResult<?> resumeJob(TspJob request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.resumeJob(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    @Override
    public TspResult<?> resumeJobDetail(TspJobDetail request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.resumeJobDetail(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    @Override
    public TspResult<?> resumeJobGroup(TspJobGroup request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.resumeJobGroup(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    /**
     * 功能说明: 设置服务端回调线程池大小
     *
     * @param callbackExecutorThreads 服务端回调线程池大小 
     */
    @Override
    public void setCallbackExecutorThreads(int callbackExecutorThreads) {
        this.callbackExecutorThreads = callbackExecutorThreads;
    }
    
    /**
     * 功能说明: 设置futureChannel连接超时时间
     *
     * @param connectTimeoutMillis futureChannel连接超时时间 
     */
    @Override
    public void setConnectTimeoutMillis(long connectTimeoutMillis) {
        this.connectTimeoutMillis = connectTimeoutMillis;
    }
    
    /**
     * 功能说明: 设置发送心跳间隔时间
     *
     * @param heartbeatBrokerInterval 发送心跳间隔时间 
     */
    @Override
    public void setHeartbeatBrokerInterval(long heartbeatBrokerInterval) {
        this.heartbeatBrokerInterval = heartbeatBrokerInterval;
    }
    
    /**
     * 功能说明: 设置netty服务器端口
     *
     * @param listenPort netty服务器端口 
     */
    @Override
    public void setListenPort(int listenPort) {
        this.listenPort = listenPort;
    }
    
    /**
     * 功能说明: 设置信号量，Oneway情况会使用，防止本地Netty缓存请求过多
     *
     * @param permitsAsync 信号量，Oneway情况会使用，防止本地Netty缓存请求过多 
     */
    @Override
    public void setPermitsAsync(int permitsAsync) {
        this.permitsAsync = permitsAsync;
    }
    
    /**
     * 功能说明: 设置信号量，异步调用情况会使用，防止本地Netty缓存请求过多
     *
     * @param permitsOneway 信号量，异步调用情况会使用，防止本地Netty缓存请求过多 
     */
    @Override
    public void setPermitsOneway(int permitsOneway) {
        this.permitsOneway = permitsOneway;
    }
    
    
    /**
     * 功能说明: 设置服务端处理请求线程池大小
     *
     * @param processorExecutorThreads 服务端处理请求线程池大小 
     */
    @Override
    public void setProcessorExecutorThreads(int processorExecutorThreads) {
        this.processorExecutorThreads = processorExecutorThreads;
    }
    
    
    /**
     * 功能说明: 设置请求超时时间
     *
     * @param sendTimeout 请求超时时间 
     */
    @Override
    public void setSendTimeout(long sendTimeout) {
        this.sendTimeout = sendTimeout;
    }
    
    /**
     * 功能说明: 设置服务器地址
     *
     * @param serverAddr 服务器地址
     */
    @Override
    public void setServerAddr(String serverAddr) {
        this.serverAddr = serverAddr;
    }
    
    
    /**
     * 功能说明: 设置任务执行端启动状态
     *
     * @param serviceState 任务执行端启动状态 
     */
    @Override
    public void setServiceState(ServiceState serviceState) {
        this.serviceState = serviceState;
    }
    
    
    /**
     * 功能说明: 设置boss循环器线程数
     *
     * @param workGroupThreads boss循环器线程数 
     */
    @Override
    public void setWorkGroupThreads(int workGroupThreads) {
        this.workGroupThreads = workGroupThreads;
    }
    
    
    @Override
    public void shutdown() throws TspException {
        synchronized (this) {
            switch (this.serviceState) {
                case CREATE_JUST:
                    throw new TspException("client is't running");
                case RUNNING:
                    try {
                        tspNettyIntance.shutdown();
                        this.serviceState = ServiceState.SHUTDOWN_ALREADY;
                        LOG.info("TSP-CLIENT: client shutdown ok server=[{}].", serverAddr);
                        System.out.println(String.format("TSP-CLIENT: client shutdown task ok server=[%s].", serverAddr));
                    } catch (TspRemotingException e) {
                        LOG.info("TSP-CLIENT: client shutdown exception server=[{}]:", serverAddr, e);
                        System.out.println(String.format("TSP-CLIENT: client shutdown task exception server=[%s]:%s", serverAddr, e.getMessage()));
                    }
                    break;
                case SHUTDOWN_ALREADY:
                    throw new TspException("client has shutdowned before, please start once");
                case START_FAILED:
                    throw new TspException("client start fail before, please start once");
            }
        }
    }
    
    @Override
    public void start() throws TspException {
        if (StringUtils.isBlank(serverAddr)) {
            throw new TspException("serverAddr is null");
        }
        
        synchronized (this) {
            INettyConfigClient nettyConfig = new NettyConfig(serverAddr);
            nettyConfig.setConnectTimeoutMillis(this.getConnectTimeoutMillis());
            nettyConfig.setCallbackExecutorThreads(this.getCallbackExecutorThreads());
            nettyConfig.setHeartbeatBrokerInterval(this.getHeartbeatBrokerInterval());
            nettyConfig.setListenPort(this.getListenPort());
            nettyConfig.setProcessorExecutorThreads(this.getProcessorExecutorThreads());
            nettyConfig.setPermitsAsync(this.getPermitsAsync());
            nettyConfig.setPermitsOneway(this.getPermitsOneway());
            nettyConfig.setWorkGroupThreads(this.getWorkGroupThreads());
            tspNettyIntance = new TspClientIntance(nettyConfig);
            switch (this.serviceState) {
                case CREATE_JUST:
                    this.serviceState = ServiceState.START_FAILED;
                    try {
                        tspNettyIntance.start();
                        this.serviceState = ServiceState.RUNNING;
                        LOG.info("TSP-CLIENT: task start ok server=[{}].", serverAddr);
                        System.out.println(String.format("TSP-CLIENT: start client ok server=[%s].", serverAddr));
                    } catch (TspRemotingException e) {
                        LOG.info("TSP-CLIENT: task start exception server=[{}] :", serverAddr, e);
                        System.out.println(String.format("TSP-CLIENT: start client exception server=[%s]: %s", serverAddr, e.getMessage()));
                    }
                    break;
                case RUNNING:
                    throw new TspException("client is running.");
                case SHUTDOWN_ALREADY:
                    throw new TspException("client has been shutdowned.");
                case START_FAILED:
                    throw new TspException("client start fail before, please start once");
            }
        }
    }
    
    
    @Override
    public TspResult<?> updateJob(TspJob request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.updateJob(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> updateJobDetailParam(TspJobDetailParam request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.updateJobDetailParam(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
    
    
    @Override
    public TspResult<?> updateJobGroup(TspJobGroup request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.updateJobGroup(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }

    /**
     * 功能说明: 获取通信客户端
     *
     * @return tspNettyIntance 通信客户端
     */
    @Override
    public void updateServerAddr(String serverAddr) {
        tspNettyIntance.getNettyConfig().setServerAddr(serverAddr);
    }

    @Override
    public TspResult<?> updateSlice(TspSlice request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.updateSlice(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }

    @Override
    public TspResult<?> updateSliceGroup(TspSliceGroup request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.updateSliceGroup(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }

    @Override
    public TspResult<?> updateTaskIdentity(TspTaskIdentity request) {
        TspResult<?> tspResult = new TspResult<Object>();
        RequestResult requestResult = tspNettyIntance.updateTaskIdentity(request, sendTimeout);
        if (requestResult.getRequestResultType() != NettyRequestResult.SUCCESS) {
            tspResult.setTspResultType(TspResultType.FAIL);
            tspResult.setErrorMessage(requestResult.getErrorMessage());
        }
        return tspResult;
    }
}
